﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;

using DbfViewer.Commands;
using Microsoft.Win32;
using System.IO;
using DbfViewer.Models;
using System.Data;
using System.ComponentModel;
using DbfViewer.Views;

namespace DbfViewer.ViewModels
{
	public class MainViewModel : ViewModelBase
	{
		#region PublicProperties

		private string viewTitle = "DbfViewer";
		public string ViewTitle
		{
			get { return viewTitle; }
			set
			{
				viewTitle = value;
				OnPropertyChanged("ViewTitle");
			}
		}

		private DataView tableView;
		public DataView TableView
		{
			get { return tableView; }
			set
			{
				tableView = value;
				OnPropertyChanged("TableView");
			}
		}

		private int selectedRowIndex;
		public int SelectedRowIndex
		{
			get { return selectedRowIndex; }
			set
			{
				selectedRowIndex = value;
				OnPropertyChanged("SelectedRowIndex");
			}
		}

		#endregion

		
		#region Constructor

		public MainViewModel()
		{
		}

		private void TableViewOnListChanged(object sender, ListChangedEventArgs e)
		{
			DataChanged = true;
		}

		#endregion

		#region Commands

		#region ApplicationMenu
		private DelegateCommand<CancelEventArgs> exitCommand;
		public ICommand ExitCommand
		{
			get { return exitCommand ?? (exitCommand = new DelegateCommand<CancelEventArgs>(args => Exit(args))); }
		}
		private void Exit(CancelEventArgs args)
		{
			if (DataChanged)
			{
				var result = MessageBox.Show("Сохранить изменения в " + shortFileName + "?",
					"DbfViewer", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
				if (result == MessageBoxResult.Yes)
				{
					Save();
					Application.Current.Shutdown();
				}
				else if (result == MessageBoxResult.No)
				{
					Application.Current.Shutdown();
				}
				else if (result == MessageBoxResult.Cancel)
				{
					args.Cancel = true;
				}
			}
			else
			{
				Application.Current.Shutdown();
			}
		}

		private DelegateCommand openCommand;
		public ICommand OpenCommand
		{
			get { return openCommand ?? (openCommand = new DelegateCommand(Open)); }
		}
		private void Open()
		{
			var dialog = new OpenFileDialog { Filter = "Таблицы (*.dbf)|*.dbf", Multiselect = false };
			dialog.InitialDirectory = Path.GetDirectoryName(Application.ResourceAssembly.Location);

			if (dialog.ShowDialog().Value)
			{
				DbfFile = new AdoNetDbfFile(dialog.FileName);
				TableView = DbfFile.Table.DefaultView;
				tableView.ListChanged += TableViewOnListChanged;
				shortFileName = Path.GetFileName(dialog.FileName);
				UpdateViewTitle();
				DataChanged = false;
			}
		}

		private void UpdateViewTitle()
		{
			ViewTitle = this.shortFileName + " - DbfViewer";
		}

		private DelegateCommand saveCommand;
		public ICommand SaveCommand
		{
			get { return saveCommand ?? (saveCommand = new DelegateCommand(Save, CanExecute)); }
		}
		private void Save()
		{
			DbfFile.Save();
			DataChanged = false;
		}

		private DelegateCommand saveAsCommand;
		public ICommand SaveAsCommand
		{
			get { return saveAsCommand ?? (saveAsCommand = new DelegateCommand(SaveAs, CanExecute)); }
		}
		private void SaveAs()
		{
			var dialog = new SaveFileDialog { Filter = "Таблицы (*.dbf)|*.dbf" };
			dialog.InitialDirectory = Path.GetDirectoryName(Application.ResourceAssembly.Location);
			if (dialog.ShowDialog().Value)
			{
				DbfFile.FileName = dialog.FileName;
				DbfFile.Save();
				DataChanged = false;
				shortFileName = Path.GetFileName(dialog.FileName);
				UpdateViewTitle();
			}
		}
		#endregion ApplicationMenu

		#region Record
		private DelegateCommand addRecordCommand;
		public ICommand AddRecordCommand
		{
			get { return addRecordCommand ?? (addRecordCommand = new DelegateCommand(AddRecord, CanExecute)); }
		}
		private void AddRecord()
		{
			var row = TableView.Table.NewRow();
			TableView.Table.Rows.Add(row);
			GoToLastRecord();
		}
		private bool CanExecute()
		{
			return TableView != null;
		}

		private DelegateCommand removeRecordCommand;
		public ICommand RemoveRecordCommand
		{
			get { return removeRecordCommand ?? (removeRecordCommand = new DelegateCommand(RemoveRecord, CanRemoveRecord)); }
		}
		private void RemoveRecord()
		{
			TableView.Table.Rows.RemoveAt(SelectedRowIndex);
		}
		private bool CanRemoveRecord()
		{
			return TableView != null && SelectedRowIndex != -1;
		}
		
		private DelegateCommand goToFirstRecordCommand;
		public ICommand GoToFirstRecordCommand
		{
			get { return goToFirstRecordCommand ?? (goToFirstRecordCommand = new DelegateCommand(GoToFirstRecord, CanGoToFirstRecord)); }
		}
		private void GoToFirstRecord()
		{
			SelectedRowIndex = 0;
		}
		private bool CanGoToFirstRecord()
		{
			return TableView != null && SelectedRowIndex != 0;
		}

		private DelegateCommand goToLastRecordCommand;
		public ICommand GoToLastRecordCommand
		{
			get { return goToLastRecordCommand ?? (goToLastRecordCommand = new DelegateCommand(GoToLastRecord, CanGoToLastRecord)); }
		}
		private void GoToLastRecord()
		{
			SelectedRowIndex = TableRowsCount - 1;
		}
		private bool CanGoToLastRecord()
		{
			return TableView != null && SelectedRowIndex != TableRowsCount - 1;
		}
		#endregion Record

		#region Table

		private DelegateCommand editTableCommand;
		public ICommand EditTableCommand
		{
			get { return editTableCommand ?? (editTableCommand = new DelegateCommand(EditTable, CanExecute)); }
		}
		private void EditTable()
		{
			TableEditViewModel model = new TableEditViewModel(DbfFile);
			TableEditView view = new TableEditView() { DataContext = model };
			view.ShowDialog();
			RefreshTableView();
		}

		private void RefreshTableView()
		{
			TableView = null;
			TableView = DbfFile.Table.DefaultView;
		}
		#endregion

		#endregion Commands

		protected IDbfFile DbfFile { get; set; }
		protected int TableRowsCount
		{
			get
			{
				return TableView.Table.Rows.Count;
			}
		}

		protected bool DataChanged { get; set; }
		private string shortFileName = null;
	}
}
